package club.janna.hello.handle;

import club.janna.hello.dao.MemoryChannelDao;
import club.janna.hello.factory.GDW376D1FrameFactory;
import club.janna.hello.frame.DataUnit;
import club.janna.hello.frame.GDW376D1;
import club.janna.hello.model.ChannelModel;
import club.janna.hello.model.F25Data;
import club.janna.hello.parser.constants.GDW376D1Statute;
import club.janna.hello.printer.BeanPrinter;
import club.janna.hello.schedule.QueryTask;
import club.janna.hello.sender.DataSender;
import club.janna.hello.util.DataConvertor;

import java.util.Date;

/**
 * Created by guopanbo on 18/4/12.
 */
public class GDW376D1Handle {

    /**
     * 处理报文
     */
    public void handle(GDW376D1 frame) {
        System.out.println("行政区划码：" + frame.getAreaCode());
        if((frame.getAddressMark() & 0b1) == 0)
            System.out.println("终端地址：" + frame.getAddress());
        short ctl = frame.getCtl();
        //传输方向dir 1：为终端发出上行
        if(ctl >> 7 == 1) {
            //启动标志位PRM 1：标识报文来自启动站
            if ((ctl >> 6 & 0b1) == 1) {
                if((ctl & 0x0f) == GDW376D1Statute.FUNCTION_REQ_CODE_LINK_TEST)
                    System.out.println("链路测试");
                short seq = frame.getSeq();
                //请求确认标志位CON，1 需要确认
                if((seq >> 4 & 0b1) == 1) {
                    //单帧 (seq >> 5 & 0b1) == 1 && (seq >> 6 & 0b1) == 1
                    if((seq >> 5 & 0b11) == 3) {
                        System.out.println("启动帧序号：" + (seq & 0x0f));
                        //链路接口检测
                        if(frame.getAfn() == GDW376D1Statute.AFN_LINK_TEST) {
                            System.out.println("链路接口检测");
                            if(frame.getData() != null && frame.getData().length >= 4) {
                                byte offset = 0;

                                DataUnit du = new DataUnit();
                                du.setDa1(Integer.toBinaryString(frame.getData()[offset ++]));
                                du.setDa2((short)frame.getData()[offset ++]);
                                du.setDt1(Integer.toBinaryString(frame.getData()[offset ++]));
                                du.setDt2((short)frame.getData()[offset ++]);

                                short pn = GDW376D1Statute.generateP(du);
                                short fn = GDW376D1Statute.generateF(du);
                                //终端信息
                                if(pn == 0) {
                                    if(fn == 1) {
                                        System.out.println("登录");
                                        ChannelModel cm = MemoryChannelDao.getInstance().doReadChannel(String.valueOf(frame.getAreaCode()) + String.valueOf(frame.getAddress()));
                                        if(cm != null) {
                                            //发送确认帧
                                            DataSender.sendData(cm.getChannel(), DataConvertor.decArray2ByteArray(GDW376D1FrameFactory.generateConfirm(frame)), null);
                                        } else {
                                            throw new RuntimeException("通道不存在！无法发送确认数据");
                                        }
                                        //建立查询任务
                                        new Thread(new QueryTask(String.valueOf(frame.getAreaCode()) + String.valueOf(frame.getAddress()), GDW376D1Statute.COLLECT_INTERVAL, frame.getAreaCode(), frame.getAddress())).start();
                                    } else if(fn == 2) {
                                        System.out.println("退出登录");
                                    } else if(fn == 3) {
                                        System.out.println("心跳");
                                        if(frame.getData().length - offset == 6) {
                                            //A1格式数据（见附录A.1）
                                            Date time = DataConvertor.getDate(DataConvertor.bcd2Dec(frame.getData()[offset ++]), DataConvertor.bcd2Dec(frame.getData()[offset ++]), DataConvertor.bcd2Dec(frame.getData()[offset ++]), DataConvertor.bcd2Dec(frame.getData()[offset ++]), DataConvertor.bcd2Dec((frame.getData()[offset ++] & 0x1f)), DataConvertor.bcd2Dec(frame.getData()[offset ++]));
                                            System.out.println(time);
                                            //System.out.println("\t秒:" + DataConvertor.bcd2Dec(frame.getData()[offset ++]));
                                            //System.out.println("\t分:" + DataConvertor.bcd2Dec(frame.getData()[offset ++]));
                                            //System.out.println("\t时:" + DataConvertor.bcd2Dec(frame.getData()[offset ++]));
                                            //System.out.println("\t日:" + DataConvertor.bcd2Dec(frame.getData()[offset ++]));
                                            //System.out.println("\t星期:" + (frame.getData()[offset] >> 5));
                                            //System.out.println("\t月:" + DataConvertor.bcd2Dec((frame.getData()[offset] & 0x1f)));
                                            //offset ++;
                                            //System.out.println("\t年:" + DataConvertor.bcd2Dec(frame.getData()[offset ++]));
                                        }
                                        ChannelModel cm = MemoryChannelDao.getInstance().doReadChannel(String.valueOf(frame.getAreaCode()) + String.valueOf(frame.getAddress()));
                                        if(cm != null) {
                                            //发送确认帧
                                            DataSender.sendData(cm.getChannel(), DataConvertor.decArray2ByteArray(GDW376D1FrameFactory.generateConfirm(frame)), null);
                                        } else {
                                            System.out.println("通道不存在！无法发送确认数据");
                                        }
                                    }
                                } else {
                                    System.out.println("pn=" + pn);
                                }
                            }
                        } else {
                            System.out.println("afn=" + frame.getAfn());
                        }
                    } else if((seq >> 5 & 0b11) == 0){
                        //多帧，中间帧
                    } else if((seq >> 5 & 0b11) == 2){
                        //多帧，开始帧
                    } else if((seq >> 5 & 0b11) == 1){
                        //多帧，结束帧
                    }
                } else {
                    //不需要确认
                }
            } else {
                //表示报文来自从动站
                //用户数据
                if((ctl & 0x0f) == GDW376D1Statute.FUNCTION_RES_USER_DATA) {
                    System.out.println("用户数据");
                    short seq = frame.getSeq();
                    //请求确认标志位CON，1 需要确认
                    if((seq >> 4 & 0b1) == 0) {
                        //单帧 (seq >> 5 & 0b1) == 1 && (seq >> 6 & 0b1) == 1
                        if ((seq >> 5 & 0b11) == 3) {
                            System.out.println("响应帧序号：" + (seq & 0x0f));
                            //查询1类数据
                            if (frame.getAfn() == GDW376D1Statute.AFN_QUERY1) {
                                System.out.println("查询1类数据");
                                if (frame.getData() != null && frame.getData().length >= 4) {
                                    byte offset = 0;

                                    DataUnit du = new DataUnit();
                                    du.setDa1(Integer.toBinaryString(frame.getData()[offset++]));
                                    du.setDa2((short) frame.getData()[offset++]);
                                    du.setDt1(Integer.toBinaryString(frame.getData()[offset++]));
                                    du.setDt2((short) frame.getData()[offset++]);

                                    short pn = GDW376D1Statute.generateP(du);
                                    short fn = GDW376D1Statute.generateF(du);
                                    System.out.printf("fn=%d, 测量点号：%d", fn, pn);
                                    //当前三相及总有/无功功率、功率因数，三相电压、电流、零序电流、视在功率
                                    if (fn == 25) {
                                        System.out.println("当前三相及总有/无功功率、功率因数，三相电压、电流、零序电流、视在功率");
                                        //数据长度：如果存在时间标签减去时间标签（6字节）后应为67字节
                                        if((seq >> 7 == 1 && frame.getData().length - 6 - 4 == 67) || (seq >> 7 == 0 && frame.getData().length - 4 == 67)) {
                                            //取出数据
                                            F25Data data = new F25Data();
                                            data.setTime(DataConvertor.getDate(0, DataConvertor.bcd2Dec(frame.getData()[offset++]), DataConvertor.bcd2Dec(frame.getData()[offset++]), DataConvertor.bcd2Dec(frame.getData()[offset++]), DataConvertor.bcd2Dec(frame.getData()[offset++]), DataConvertor.bcd2Dec(frame.getData()[offset++])));
                                            data.setPower(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setPowerA(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setPowerB(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setPowerC(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setReactivePower(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setReactivePowerA(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setReactivePowerB(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setReactivePowerC(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setPowerFactor(GDW376D1Statute.A5(frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setPowerFactorA(GDW376D1Statute.A5(frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setPowerFactorB(GDW376D1Statute.A5(frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setPowerFactorC(GDW376D1Statute.A5(frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setVoltageA(GDW376D1Statute.A7(frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setVoltageB(GDW376D1Statute.A7(frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setVoltageC(GDW376D1Statute.A7(frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setCurrentA(GDW376D1Statute.A25(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setCurrentB(GDW376D1Statute.A25(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setCurrentC(GDW376D1Statute.A25(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setCurrentZero(GDW376D1Statute.A25(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setApparentPower(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setApparentPowerA(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setApparentPowerB(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            data.setApparentPowerC(GDW376D1Statute.A9(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            BeanPrinter.print(data, "\t\t");
                                            System.out.println("pfc:" + DataConvertor.bcd2Dec(frame.getData()[offset++]));
                                            //时间
                                            System.out.println(GDW376D1Statute.parseTp16(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                        } else {
                                            throw new RuntimeException("data length invalid");
                                        }
                                    } else if(fn == 129) {
                                        //当前正向有功电能示值
                                        System.out.println("当前正向有功电能示值");
                                        //数据长度：如果存在时间标签减去时间标签（6字节）后应为67字节
                                        if((seq >> 7 == 1 && frame.getData().length - 6 - 4 == 31) || (seq >> 7 == 0 && frame.getData().length - 4 == 31)) {
                                            System.out.println("采集时间：" + DataConvertor.getDate(0, DataConvertor.bcd2Dec(frame.getData()[offset++]), DataConvertor.bcd2Dec(frame.getData()[offset++]), DataConvertor.bcd2Dec(frame.getData()[offset++]), DataConvertor.bcd2Dec(frame.getData()[offset++]), DataConvertor.bcd2Dec(frame.getData()[offset++])));
                                            int c = DataConvertor.bcd2Dec(frame.getData()[offset++]);
                                            System.out.println("费率数：" + c);
                                            System.out.println("正向有功总：" + GDW376D1Statute.A14(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            for(int i = 0;i < c; i ++)
                                                System.out.println("费率" + (i + 1) + "：" + GDW376D1Statute.A14(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                            System.out.println("pfc:" + DataConvertor.bcd2Dec(frame.getData()[offset++]));
                                            //时间
                                            System.out.println(GDW376D1Statute.parseTp16(frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++], frame.getData()[offset++]));
                                        } else {
                                            throw new RuntimeException("data length invalid");
                                        }
                                    }
                                }
                            }
                        } else {
                            //多帧
                        }
                    } else {
                        //需要确认
                    }
                } else {

                }
            }
        } else {
            //为主站发出下行
        }
    }


}
